﻿using MediatR;
using Microsoft.Extensions.Logging;
using Sgr.Data;
using Sgr.Domain.Uow;
using Sgr.Identity.Services;
using Sgr.Security.Permissions;
using Sgr.UPMS.Domain.Organizations;
using Sgr.UPMS.Domain.Roles;
using Sgr.UPMS.Domain.Users;
using Sgr.UPMS.Infrastructure.Repositories;
using Sgr.Utilities;

namespace Sgr.UPMS.Infrastructure.Sead
{
    public class SuperAdminDataBaseInitialize : IDataBaseInitialize
    {
        private static readonly string[] ResourcesToInclude = new string[] { "Resources" };
        private static readonly string[] UserIncludes = { "Roles" };

        private readonly IUnitOfWorkManager _unitOfWorkManager;

        private readonly IOrganizationManage _organizationManage;
        private readonly IOrganizationRepository _organizationRepository;

        private readonly IRoleManage _roleManage;
        private readonly IRoleRepository _roleRepository;

        private readonly IEnumerable<IPermissionProvider> _permissionProviders;

        private readonly IUserManage _userManage;
        private readonly IUserRepository _userRepository;
        private readonly IPasswordHashService _passwordHashService;

        private readonly ILogger<SuperAdminDataBaseInitialize> _logger;

        public SuperAdminDataBaseInitialize(
            IUnitOfWorkManager unitOfWorkManager,
            IOrganizationManage organizationManage,
            IOrganizationRepository organizationRepository,
            IRoleManage roleManage,
            IRoleRepository roleRepository,
            IUserManage userManage,
            IUserRepository userRepository,
            IPasswordHashService passwordHashService,
            IEnumerable<IPermissionProvider> permissionProviders,
            ILogger<SuperAdminDataBaseInitialize> logger)
        {
            _unitOfWorkManager = unitOfWorkManager;
            _organizationManage = organizationManage;
            _organizationRepository = organizationRepository;
            _roleManage = roleManage;
            _roleRepository = roleRepository;
            _permissionProviders = permissionProviders;
            _userManage = userManage;
            _userRepository = userRepository;
            _passwordHashService = passwordHashService;
            _logger = logger;
        }

        /// <summary>
        /// 获取初始化执行顺序，值越大越靠后执行
        /// </summary>
        public int Order => 950;

        public async Task Initialize()
        {
            // 检查超级管理员组织是否存在，如果存在则不执行初始化
            var adminOrg = await _organizationRepository.GetAsync(Constant.SUPER_ADMIN_ORG_ID);
            if (adminOrg != null)
                return;

            // 初始化超级管理员组织
            await InitializeAdminOrganizationAsync();

            // 获取分类后的权限清单
            var (superAdminPerms, systemAdminPerms, normalUserPerms) = await GetCategorizedPermissionsAsync();

            //更新超级管理员角色
            await UpdateRoleAsync(Constant.SUPER_ADMIN_ORG_ID, Constant.SUPER_ADMIN_ROLE_ID, "运维人员", 0, superAdminPerms);

            //更新系统管理员角色
            await UpdateRoleAsync(Constant.SUPER_ADMIN_ORG_ID, Constant.SYSTEM_ADMIN_ROLE_ID, "系统管理员", 1, systemAdminPerms);

            //更新普通用户角色
            await UpdateRoleAsync(Constant.SUPER_ADMIN_ORG_ID, Constant.NORMAL_USER_ROLE_ID, "普通用户", 2, normalUserPerms);

            //创建超级管理员用户
            await CreateSuperAdminUserAsync();
        }

        /// <summary>
        /// 初始化超级管理员组织
        /// </summary>
        /// <returns></returns>
        private async Task InitializeAdminOrganizationAsync()
        {
            using var uow = _unitOfWorkManager.Begin(requiresNew: true);
            try
            {
                Organization adminOrg = await _organizationManage.CreateNewAsync(Constant.SUPER_ADMIN_ORG_ID, "SGR", "", null, null);
                await _organizationRepository.InsertAsync(adminOrg);
                await uow.CommitAsync();

                _logger.LogInformation("系统组织初始化完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "系统组织初始化失败");
                await uow.RollbackAsync();
            }
        }

        /// <summary>
        /// 确保超管用户存在
        /// </summary>
        /// <returns></returns>
        private async Task CreateSuperAdminUserAsync()
        {
            _logger.LogInformation($"开始初始化系统用户............");

            var (superAdminUserName, superAdminPassword) = GetSuperAdminCredentials();

            using var uow = _unitOfWorkManager.Begin(requiresNew: true);
            try
            {
                var role = await _roleRepository.GetAsync(Constant.SUPER_ADMIN_ROLE_ID);

                if (role != null)
                {
                    var user = await _userRepository.GetByLoginNameAsync(superAdminUserName, UserIncludes);
                    if (user == null)
                    {
                        user = await _userManage.CreateNewAsync(
                            superAdminUserName,
                            _passwordHashService,
                            superAdminPassword,
                            true,
                            Constant.SUPER_ADMIN_ORG_ID);
                        user.Id = Constant.SUPER_ADMIN_USER_ID;
                        user.SetUserInfo("运维人员", Gender.Male, null, null);
                        user.DifferenceUpdateRoles(new long[] { Constant.SUPER_ADMIN_ROLE_ID }, true);

                        await _userRepository.InsertAsync(user);
                    }
                }

                await uow.CommitAsync();

                _logger.LogInformation("系统用户初始化完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "系统用户初始化失败");
                await uow.RollbackAsync();
            }
        }

        /// <summary>
        /// 获取超级管理员账号信息
        /// </summary>
        /// <returns>(用户名, 密码)</returns>
        private (string UserName, string Password) GetSuperAdminCredentials()
        {
            // 从环境变量获取
            string? envUserName = Environment.GetEnvironmentVariable("SGR_SUPER_ADMIN_USERNAME");
            string? envPassword = Environment.GetEnvironmentVariable("SGR_SUPER_ADMIN_PASSWORD");

            // 验证用户名
            if (!string.IsNullOrEmpty(envUserName) && ValidateUsername(envUserName))
            {
                //_logger.LogInformation("使用环境变量中的超级管理员用户名");
            }
            else
            {
                _logger.LogInformation("未设置超级管理员用户名，使用默认用户名");
                envUserName = Constant.SUPER_ADMIN_USER_NAME;
            }

            // 验证密码
            if (!string.IsNullOrEmpty(envPassword) && StringHelper.SgrPasswordComplexityIsCompliant(envPassword))
            {
                //_logger.LogInformation("使用环境变量中的超级管理员密码");
            }
            else
            {
                _logger.LogInformation("未设置超级管理员密码，使用默认密码");
                envPassword = Constant.SUPER_ADMIN_PASS_WORD;
            }

            return (envUserName, envPassword);
        }

        /// <summary>
        /// 验证用户名是否合法
        /// </summary>
        /// <param name="username">用户名</param>
        /// <returns>是否合法</returns>
        private static bool ValidateUsername(string username)
        {
            // 用户名不能为空且长度在3-20之间
            if (string.IsNullOrWhiteSpace(username) || username.Length < 3 || username.Length > 20)
                return false;

            // 用户名只能包含字母、数字、下划线
            return username.All(c => char.IsLetterOrDigit(c) || c == '_');
        }

        private async Task UpdateRoleAsync(long orgId, long roleId, string roleName, int orderNumber, IEnumerable<string> superAdminPerms)
        {
            // 应该添加参数验证
            if (string.IsNullOrEmpty(roleName))
                throw new ArgumentException("角色名称不能为空", nameof(roleName));

            Check.NotNull(superAdminPerms, nameof(superAdminPerms));

            using var uow = _unitOfWorkManager.Begin(requiresNew: true);
            try
            {
                var role = await _roleRepository.GetAsync(roleId, ResourcesToInclude);
                bool roleExists = role != null;
                if (!roleExists)
                {
                    role = await _roleManage.CreateNewAsync(roleName, orgId, orderNumber, "系统自动创建");
                    role.Id = roleId;
                    role.DifferenceUpdateFunctionalPermission(ResourceType.FunctionalPermission, superAdminPerms.ToArray());
                    await _roleRepository.InsertAsync(role);
                }

                await uow.CommitAsync();

                if (!roleExists)
                    _logger.LogInformation($"系统角色 {roleName} 初始化完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"系统角色 {roleName} 初始化失败");
                await uow.RollbackAsync();
            }
        }

        /// <summary>
        /// 根据授权类型获取功能权限清单
        /// </summary>
        /// <returns>包含三种角色类型的功能权限清单</returns>
        private async Task<(IEnumerable<string> SuperAdminPermissions,
            IEnumerable<string> SystemAdminPermissions,
            IEnumerable<string> NormalUserPermissions)> GetCategorizedPermissionsAsync()
        {
            var superAdminPermissions = new HashSet<string>();
            var systemAdminPermissions = new HashSet<string>();
            var normalUserPermissions = new HashSet<string>();

            // 从所有权限提供者获取功能权限
            foreach (var provider in _permissionProviders)
            {
                var permissions = await provider.GetFunctionPermissionsAsync();
                foreach (var permission in permissions)
                {
                    // 检查权限是否包含对应的角色类型
                    if (permission.DefaultGrantRoleType.HasFlag(GrantRoleType.SuperAdmin))
                    {
                        superAdminPermissions.Add(permission.Name);
                    }

                    if (permission.DefaultGrantRoleType.HasFlag(GrantRoleType.SystemAdmin))
                    {
                        systemAdminPermissions.Add(permission.Name);
                    }

                    if (permission.DefaultGrantRoleType.HasFlag(GrantRoleType.NormalUser))
                    {
                        normalUserPermissions.Add(permission.Name);
                    }
                }
            }

            return (superAdminPermissions, systemAdminPermissions, normalUserPermissions);
        }
    }
}